package business.global.pk.zjh;

import java.util.*;
import java.util.stream.Collectors;

import business.global.room.base.AbsRoomPos;
import business.global.room.base.AbsRoomSet;
import business.global.room.base.RoomPlayBack;
import business.zjh.c2s.cclass.*;
import business.zjh.c2s.iclass.*;
import cenum.PrizeType;

import cenum.RoomTypeEnum;
import cenum.room.SetState;
import cenum.room.TrusteeshipState;
import com.ddm.server.common.CommLogD;
import com.ddm.server.common.utils.CommMath;
import com.ddm.server.common.utils.CommTime;
import com.ddm.server.common.utils.Lists;
import com.ddm.server.websocket.def.ErrorCode;
import com.ddm.server.websocket.handler.requset.WebSocketRequest;
import com.google.gson.Gson;
import business.zjh.c2s.cclass.ZJH_define.ZJH_StatusType;
import core.db.entity.clarkGame.GameSetBO;
import core.db.service.clarkGame.GameSetBOService;
import core.ioc.ContainerMgr;
import jsproto.c2s.cclass.BaseSendMsg;
import jsproto.c2s.cclass.pk.PKRoom_RecordPosInfo;
import jsproto.c2s.cclass.pk.Victory;
import jsproto.c2s.cclass.playback.PlayBackData;
import lombok.Data;
import org.apache.commons.collections.CollectionUtils;

/**
 * 牛牛一局游戏逻辑
 *
 * @author zaf
 */
public class ZJHRoomSet extends AbsRoomSet {

    // public static final int[] qipaitime = {15000,30000,60000};
    // public ZJHRoom<?> room = null;
    public long m_startMS = 0;
    public ZJHSetCard setCard = null;
    public ZJHRoom_SetEnd setEnd = new ZJHRoom_SetEnd();
    // public GameSetBO bo = null;
    private int m_backerPos = -1; // 庄家 -1:标识没有庄家
    protected int m_opPos = -1; // 操作位置
    public int m_bottomPoint = -1; // 底注
    public int m_basePoint = -1; // 底注
    public SetState state = SetState.Init; // 牌局状态
    public List<Integer> cardTypeList = new ArrayList<Integer>(); // 牌类型
    public List<Boolean> playingList = new ArrayList<Boolean>(); // 每局玩家
    public ArrayList<Integer> addScoreList = new ArrayList<Integer>(); // 押注
    public ArrayList<Integer> statusCardList = new ArrayList<Integer>(); // 比牌状态
    protected HashMap<Integer, List<Integer>> hMap = new HashMap<Integer, List<Integer>>();
    protected HashMap<Integer, ArrayList<Victory>> m_RecordHMap = new HashMap<Integer, ArrayList<Victory>>(); // 记录比牌输赢
    protected static final int MINSURPLUSPLAYERNUM = 2;// 剩余人数结束当前局
    protected static final int ONEPLAYERPLAYINGTIME = 15000;// 每个玩家操作时间
    protected static final int INITTIME = 12000;// 初始化时间
    protected static final int WAITTRUSTEESHIPTIME = 3000;// 托管延迟2s
    // protected static final int MAXTURNS = 30;//最大轮数
    protected static final int ENDSETINVALIT = 2000;// 最大轮数
    protected int m_currTurns = 1;// 当前轮数
    protected int m_currTurnOpPos = -1;// 当前轮其实操作位置
    protected int m_QuanYaPos = -1;// 全压
    protected Victory m_refund = new Victory();// 全压退款
    protected long m_startMSGlod = 0;

    public ZJHRoom room = null;
    public long startMS = 0;
    public GameSetBO bo = null;
    // public ZJHSetCard setCard = null;
    // public ZJHRoom_SetEnd setEnd = new ZJHRoom_SetEnd();
    // private int m_backerPos = -1; //庄家 -1:标识没有庄家
    public boolean m_isRandBackPos = false;// 是否随机庄家
    public ArrayList<Double> sportsPointList = null;
    public ArrayList<Double> yiKaoPointList = null;
    public List<Integer> betList; // 下注分数
    public List<Boolean> checkCardList; // 亮牌玩家
    public List<Boolean> openCardList; // 开牌玩家
    // public List<Boolean> playingList; //每局玩家
    public List<Victory> callbackerList; // 是否抢过庄 victory：pos:抢庄位置 num 抢庄陪数
    public List<Integer> crawTypeList;// 牛牛类型
    public ArrayList<Integer> pointList; // 得分
    // HashMap<Integer, List<Integer>> hMap = new HashMap<Integer, List<Integer>>();
    protected static final int TUIZHUSETID = 3;
    // protected static final int MAXBETNUM = 10;//推注为底分的最大陪数
    // protected static final int WAITTRUSTEESHIPTIME = 3000;//托管延迟2s
    protected static final int TUIZHULIST[] = { 0, 5, 10 };
    protected RoomPlayBack roomPlayBack; // 回放
    Map<Integer, Integer> winControlMap;
    // -1：表示没有人上分中
    public int upwardTimePos = -1;
    // 点击上分时的时间
    public int upwardOpTime = 0;

    @SuppressWarnings("rawtypes")
    public ZJHRoomSet(ZJHRoom room, Map<Integer, Integer> winControlMap) {
        super(room.getCurSetID());
        this.room = room;
        this.winControlMap = null == winControlMap ? new HashMap<>() : winControlMap;
        this.checkCardList = new ArrayList<>(Collections.nCopies(this.room.getMaxPlayerNum(), false));
        this.openCardList = new ArrayList<>(Collections.nCopies(this.room.getMaxPlayerNum(), false));
        this.playingList = new ArrayList<>(Collections.nCopies(this.room.getMaxPlayerNum(), false));
        this.callbackerList = new ArrayList<>();
        this.betList = new ArrayList<>(Collections.nCopies(this.room.getMaxPlayerNum(), 0));
        this.crawTypeList = new ArrayList<>(Collections.nCopies(this.room.getMaxPlayerNum(), 0));
        this.pointList = new ArrayList<>(Collections.nCopies(this.room.getMaxPlayerNum(), 0));
        this.initSportsPointList();
        // 回放记录添加游戏配置
        this.addGameConfig();

        for (int i = 0; i < this.room.getMaxPlayerNum(); i++) {
            this.playingList.add(false);
            this.addScoreList.add(0);
            this.cardTypeList.add(-1);
            this.statusCardList.add(0);
            this.m_RecordHMap.put(i, new ArrayList<Victory>());
        }
        int[] arr = { 0, 1, 2, 3, 5 };
        this.m_bottomPoint = this.room.getConfigMgr().getBottomPointList().get(this.room.roomCfg.dizhu);
        this.m_basePoint = this.room.getConfigMgr().getBottomPointList().get(this.room.roomCfg.dizhu);
        if (this.room.roomCfg.menpailunshu > 0) {
            this.m_bottomPoint *= arr[this.room.roomCfg.menpailunshu];
        }
        // if(PrizeType.Gold == this.room.getPrizeType()){
        // m_bottomPoint *= this.room.getBaseMark();
        // }
        this.m_refund.setPos(-1);

        this.startSet();
    }

    /**
     * 获取房间信息
     *
     * @return
     */
    public ZJHRoom getRoom() {
        return room;
    }

    private void initSportsPointList() {
        if (RoomTypeEnum.UNION.equals(this.room.getRoomTypeEnum())) {
            this.sportsPointList = new ArrayList<>(Collections.nCopies(this.room.getMaxPlayerNum(), 0D));
            // 一考分数 panvc
            this.yiKaoPointList = new ArrayList<>(Collections.nCopies(this.room.getMaxPlayerNum(), 0D));
        }
    }

    /**
     * 回放记录添加游戏配置
     */
    @Override
    public void addGameConfig() {
        this.getRoomPlayBack().addPlaybackList(
                SZJH_Config.make(room.getRoomCfg(), this.room.getRoomTyepImpl().getRoomTypeEnum()), null);
    }

    /**
     * 获取房间回放记录
     *
     * @return
     */
    public RoomPlayBack getRoomPlayBack() {
        if (null == this.roomPlayBack) {
            this.roomPlayBack = new ZJHRoomPlayBackImpl(this.room);
        }
        return this.roomPlayBack;
    }

    /*
     * 设置默认庄家位置
     **/
    public void setDefeault() {
        if (this.room.getCurSetID() == 1) {
            ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPid(this.room.getOwnerID());
            if (null == roomPos) {
                CommLogD.error("setDefeault not find owner posinfo");
                m_backerPos = 0;
            } else {
                m_backerPos = 0;
            }
            long pid = this.room.getRoomPosMgr().getPosByPosID(m_backerPos).getPid();
            while (pid <= 0) {
                m_backerPos++;
                pid = this.room.getRoomPosMgr().getPosByPosID(m_backerPos).getPid();
            }
            m_currTurnOpPos = m_opPos = m_backerPos;
        } else {
            m_backerPos = this.room.getCallBacker();

            int nextOpPos = this.nextOpPos(m_backerPos);
            m_currTurnOpPos = m_opPos = nextOpPos;
        }

        for (int i = 0; i < this.room.getPlayerNum(); i++) {
            if (!this.playingList.get(i))
                continue;
            this.addScoreList.set(i, this.addScoreList.get(i) - this.m_basePoint);
        }
    }

    public int nextOpPos(int opPos) {
        int nextOpPos = 0;
        for (int i = 0; i < this.room.getMaxPlayerNum(); i++) {
            nextOpPos = (opPos + 1) % this.room.getMaxPlayerNum();
            if (!this.playingList.get(nextOpPos)) {
                continue;
            }
            if (this.cheakCardStatus(nextOpPos, ZJH_StatusType.ComporeLose.value() | ZJH_StatusType.GiveUp.value())) {
                continue;
            }
            return nextOpPos;
        }
        return opPos;
    }

    /**
     * 结算
     */
    public void resultCalc() {

        if (this.cardTypeList.get((int) (Math.random() * this.room.getMaxPlayerNum())) == -1) {
            this.getCardTypeList();
        }

        // 处理跟到底的用户 panvc
        List<Integer> gddList = Lists.newArrayList();
        for (int i = 0; i < this.room.getMaxPlayerNum(); i++) {
            if (!this.playingList.get(i))
                continue;
            if (this.cheakCardStatus(i,
                    ZJH_define.ZJH_StatusType.ComporeLose.value() | ZJH_define.ZJH_StatusType.GiveUp.value()))
                continue;
            gddList.add(i);
            for (int j = 0; j < this.room.getMaxPlayerNum(); j++) {
                if (i == j)
                    continue;
                if (!this.playingList.get(j))
                    continue;
                if (this.cheakCardStatus(j,
                        ZJH_define.ZJH_StatusType.ComporeLose.value() | ZJH_define.ZJH_StatusType.GiveUp.value()))
                    continue;
                gddList.add(j);

                ZJHRoomPos roomPosi = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(i);
                ZJHRoomPos roomPosj = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(j);

                if (ZJHGameLogic.CompareCard(roomPosi.privateCards, roomPosj.privateCards,
                        this.room.roomCfg.tongpaishuying)) {
                    this.setCardStatus(i, ZJH_define.ZJH_StatusType.ComporeWin.value());
                    this.setCardStatus(j, ZJH_define.ZJH_StatusType.ComporeLose.value());
                    // this.m_RecordHMap.get(i).add(new Victory(j,
                    // ZJH_StatusType.ComporeWin.value()));
                    // this.m_RecordHMap.get(j).add(new Victory(i,
                    // ZJH_StatusType.ComporeLose.value()));
                    roomPosj.addLose(1);
                } else {
                    this.setCardStatus(j, ZJH_StatusType.ComporeWin.value());
                    this.setCardStatus(i, ZJH_StatusType.ComporeLose.value());
                    // this.m_RecordHMap.get(i).add(new Victory(j,
                    // ZJH_StatusType.ComporeLose.value()));
                    // this.m_RecordHMap.get(j).add(new Victory(i,
                    // ZJH_StatusType.ComporeWin.value()));
                    roomPosi.addLose(1);
                }
            }
        }

        // 处理跟到底的用户对比记录 panvc
        if (CollectionUtils.isNotEmpty(gddList)) {
            List<Integer> collect = gddList.stream().distinct().sorted().collect(Collectors.toList());
            for (Integer posIdI : collect) {
                int statusI = this.statusCardList.get(posIdI);
                for (Integer posIdJ : collect) {
                    if (posIdI == posIdJ)
                        continue;
                    this.m_RecordHMap.get(posIdI).add(new Victory(posIdJ, statusI));
                }
            }
        }

        for (int i = 0; i < this.room.getMaxPlayerNum(); i++) {
            if (!this.playingList.get(i))
                continue;
            if (this.cheakCardStatus(i, ZJH_StatusType.ComporeLose.value() | ZJH_StatusType.GiveUp.value()))
                continue;
            this.addScoreList.set(i, 0);
            for (int j = 0; j < this.room.getMaxPlayerNum(); j++) {
                if (!this.playingList.get(j))
                    continue;
                if (i == j)
                    continue;
                this.addScoreList.set(i, this.addScoreList.get(i) - this.addScoreList.get(j));
            }

            ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(i);
            roomPos.addWin(1);

            this.setCardStatus(i, ZJH_StatusType.OpenCard.value());

            this.room.setCallBacker(i);
            break;
        }

        // if(this.room.roomCfg.xiqian.size()==2){
        for (int i = 0; i < this.room.getMaxPlayerNum(); i++) {
            if (!this.playingList.get(i))
                continue;
            if (!(this.cardTypeList.get(i) == ZJHGameLogic.ZJH_PAOZI && this.room.roomCfg.xiqian.contains(0)
                    || this.cardTypeList.get(i) == ZJHGameLogic.ZJH_SHUNJIN && this.room.roomCfg.xiqian.contains(1)))
                continue;
            if (this.cheakCardStatus(i, ZJH_StatusType.GiveUp.value()))
                continue;
            int num = this.room.getConfigMgr().getBottomPointList().get(this.room.roomCfg.dizhu) * this.room
                    .getConfigMgr().getXiQianBeiShuList().get(this.cardTypeList.get(i) - ZJHGameLogic.ZJH_SHUNJIN);
            for (int j = 0; j < this.room.getMaxPlayerNum(); j++) {
                if (!this.playingList.get(j))
                    continue;
                if (i == j)
                    continue;
                this.addScoreList.set(i, this.addScoreList.get(i) + num);
                this.addScoreList.set(j, this.addScoreList.get(j) - num);
            }
        }
        // }

    }

    /*
     * 设置牌的状态
     **/
    public void setCardStatus(int pos, int statusType) {
        int status = this.statusCardList.get(pos);
        if (ZJH_StatusType.ComporeLose.value() == statusType || ZJH_StatusType.ComporeWin.value() == statusType
                || ZJH_StatusType.GiveUp.value() == statusType) {
            status = status & ZJH_StatusType.WinLoseGiveUp.value();
        }
        this.statusCardList.set(pos, status | statusType);
    }

    /*
     * 获取牌型
     */
    public void getCardTypeList() {
        for (int i = 0; i < this.room.getMaxPlayerNum(); i++) {
            if (!this.playingList.get(i))
                continue;
            ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(i);
            this.cardTypeList.set(i, ZJHGameLogic.GetCardType(roomPos.privateCards));
        }
        if (this.cardTypeList.size() > 0)
            CommLogD.info("getCardTypeList list:" + this.cardTypeList.toString());
    }

    // 叫庄
    public void onCallBacker(WebSocketRequest request, CZJH_CallBacker Backer) {
    }

    // 下注
    public void onAddBet(WebSocketRequest request, CZJH_AddBet addBet) {
    }

    // 下庄
    public void onShimosho(WebSocketRequest request, CZJH_Shimosho addBet) {
        request.error(ErrorCode.NotAllow, "onShimosho error do not ");
    }

    // 抢庄结束
    public void onHogEnd() {
        // TODO 自动生成的方法存根

    }

    /**
     * 开始设置
     */
    public void startSet() {
        // 设置参与游戏的玩家
        for (AbsRoomPos pos : this.room.getRoomPosMgr().getPosList()) {
            ZJHRoomPos roomPos = (ZJHRoomPos) pos;
            if ((pos.isReady() && this.room.getCurSetID() == 1) || (this.room.getCurSetID() > 1 && pos.getPid() != 0)) {
                this.setPosPlaying(pos.getPosID(), true);
                roomPos.setPlayTheGame(true);
            }
        }

        // 洗底牌
        this.setCard = new ZJHSetCard(this);
        // 是否开启神牌模式
        if (room.isGodCard()) {
            godCard();
        }
        for (int i = 0; i < this.room.getXiPaiList().size(); i++) {
            this.setCard.onXiPai();
        }
        this.room.getXiPaiList().clear();

        // 对每个位置的人设置牌
        int index = this.room.getCurSetID();
        List<ArrayList<Integer>> lists = new ArrayList<ArrayList<Integer>>();
        List<ArrayList<Integer>> lists2 = new ArrayList<ArrayList<Integer>>();
        boolean haveGod = false;
        int winIndex = -1;
        int loseIndex = -1;

        if (winControlMap != null && winControlMap.containsKey(1)) {// isGodUser(pid)
            haveGod = true;
            winIndex = winControlMap.get(1);
        }
        if (winControlMap != null && winControlMap.containsKey(0)) {// isGodUser(pid)
            haveGod = true;
            loseIndex = winControlMap.get(0);
        }
        for (int i = 0; i < this.room.getPlayerNum(); i++) {
            if (this.room.getRoomPosMgr().getPosByPosID(i) == null) {
                continue;
            }
            long pid = this.room.getRoomPosMgr().getPosByPosID(i).getPid();
            if (isGodUser(pid)) {
                haveGod = true;
                break;
            }
        }
        for (int i = 0; i < this.room.getPlayerNum(); i++) {
            index = (index + 1) % this.room.getPlayerNum();
            ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(index);
            // 如果是DEBUG模式发送神牌
            if (room.isGodCard() && hMap.get(index) != null) {
                roomPos.init(hMap.get(index), null, 0);
            } else {
                ArrayList<Integer> l1 = this.setCard.popList(this.room.maxCardCount);
                if (haveGod) {
                    lists.add(l1);
                    lists2.add(l1);
                } else {
                    roomPos.init(l1);
                }
            }
        }

        if (haveGod && !room.isGodCard()) {
            int maxIndex = 0;
            int minIndex = 0;
            for (int i = 1; i < lists.size(); i++) {
                if (!ZJHGameLogic.CompareCard(lists.get(maxIndex), lists.get(i), this.room.roomCfg.tongpaishuying)) {
                    maxIndex = i;
                }
                if (ZJHGameLogic.CompareCard(lists.get(minIndex), lists.get(i), this.room.roomCfg.tongpaishuying)) {
                    minIndex = i;
                }
            }
            if (maxIndex != winIndex && winIndex != -1) {
                ArrayList<Integer> l1 = lists.get(maxIndex);
                ArrayList<Integer> l2 = lists.get(winIndex);
                lists.set(winIndex, l1);
                lists.set(maxIndex, l2);
            }
            if (minIndex != loseIndex && loseIndex != -1) {
                ArrayList<Integer> l1 = lists.get(minIndex);
                ArrayList<Integer> l2 = lists.get(loseIndex);
                lists.set(loseIndex, l1);
                lists.set(minIndex, l2);
            }
            index = this.room.getCurSetID();
            for (int i = 0; i < this.room.getPlayerNum(); i++) {
                index = (index + 1) % this.room.getPlayerNum();
                ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(index);
                if (roomPos == null) {
                    continue;
                }
                roomPos.init(lists.get(index));
            }
            winControlMap.clear();
        }

        // this.status = getStartStatus();
        this.startMS = CommTime.nowMS();
        this.setDefeault();

        boolean unNotified = true;
        // 开始发牌
        for (AbsRoomPos pos : this.room.getRoomPosMgr().getAllPosList()) {
            ZJHRoomPos roomPos = (ZJHRoomPos) pos;
            if (roomPos.getPid() > 0) {
                if (unNotified) {
                    unNotified = false;
                    this.getRoomPlayBack().playBack2Pos(roomPos,
                            SZJH_SetStart.make(this.room.getRoomID(), this.getNotify_set(roomPos.getPid())),
                            ((ZJHRoomPosMgr) this.room.getRoomPosMgr()).getAllPlayBackNotify());
                } else {
                    this.room.getRoomPosMgr().notify2Pos(roomPos,
                            SZJH_SetStart.make(this.room.getRoomID(), this.getNotify_set(roomPos.getPid())));
                }
            }
        }

        this.room.getRoomPosMgr().setAllLatelyOutCardTime();

        this.recordRoomPosPointBeginStart(); // 设置房间初始值 panvc
        this.room.getTrusteeship().setTrusteeshipState(TrusteeshipState.Normal);
    }

    public boolean isGodUser(long pid) {
        if (this.room.getConfigMgr().getPidList().contains((int) pid)) {
            return true;
        }
        return false;
    }

    public void onWinControl(CZJH_WinControl req) {
        winControlMap.put(req.flag, req.pos);
    }

    /**
     * 局结束
     */
    public void endSet() {
        if (this.state == SetState.Settle || this.state == SetState.End)
            return;
        this.state = SetState.Settle;
        setEnd(true);
        this.calcPoint();
        setRecordPosInfoList();
        // 设置默认牌为[] panvc
        ArrayList<ArrayList<Integer>> cards = new ArrayList<>(
                Collections.nCopies(this.room.getMaxPlayerNum(), Lists.newArrayList()));
        this.room.getRoomPosMgr().getPosList().forEach(x -> {
            if (x.getPid() > 0) {
                // cards.add(((ZJHRoomPos) x).getNotifyCard(x.getPid()));
                // 设置玩家的牌 panvc
                cards.set(x.getPosID(), ((ZJHRoomPos) x).getNotifyCard(x.getPid()));
                x.setTimeSec(CommTime.nowSecond());
            }
        });
        // 广播
        this.getRoomPlayBack()
                .playBack2All(SZJH_SetEnd.make(this.room.getRoomID(), SetState.End.value(), this.m_startMS,
                        this.cardTypeList, this.addScoreList, this.sportsPointList, this.statusCardList,
                        this.m_RecordHMap, m_refund, cards));
        // 记录回放码
        roomPlayBack();// zhaozw IMPORTANT 回放

        int leftPlayingCount = this.getRoom().getPlayingCount() - this.getRoom().getKillPlayerCount();

        // 只有一个人房间结束
        boolean roomEnd = false;
        if (leftPlayingCount <= 1) {
            this.getRoom().setAutoDismiss(false);
            this.getRoom().doDissolveRoom(false);
            roomEnd = true;
        }
        // 房间结束所有人统一结算，不再单独结算，防止被踢的人重复结算
        if (!roomEnd) {
            // YSJVB 把要踢的人踢了
            this.getRoom().killPlayerByMengZhuMark();
        }

        this.state = SetState.End;
    }

    protected void setRecordPosInfoList() {
        // 记录玩家信息和简介
        for (AbsRoomPos pos : this.room.getRoomPosMgr().getAllPosList()) {
            ZJHRoomPos roomPos = (ZJHRoomPos) pos;
            if (roomPos != null && roomPos.getPid() > 0 && roomPos.isPlayTheGame()) {
                PKRoom_RecordPosInfo posInfo = new PKRoom_RecordPosInfo();
                posInfo.flatCount = roomPos.getFlat();
                posInfo.loseCount = roomPos.getLose();
                posInfo.winCount = roomPos.getWin();

                posInfo.point = roomPos.getPoint();
                posInfo.pos = roomPos.getPosID();
                posInfo.pid = roomPos.getPid();
                posInfo.setSex(roomPos.getSex());
                posInfo.setName(roomPos.getName());
                posInfo.setSportsPoint(roomPos.sportsPoint());
                posInfo.setHeadImageUrl(roomPos.getHeadImageUrl());
                this.room.allRecordPosInfoList.put(roomPos.getPid(), posInfo);
                this.room.allPlayerList.put(roomPos.getPid(), roomPos.roomPlayerPos());

                if (roomPos.isLeaveNextSet()) {
                    this.room.leavePosInfoList.put(roomPos.getPid(), posInfo);
                }
            }
        }
    }

    /**
     * 如果是房卡类型，才需要回放记录 zhaozw
     */
    public void roomPlayBack() {
        if (this.checkExistPrizeType(PrizeType.RoomCard)) {
            PlayBackData playBackData = new PlayBackData(this.room.getRoomID(),
                    this.room.getCurSetID(), 0, this.room.getCount(),
                    this.room.getRoomKey(),
                    this.room.getBaseRoomConfigure().getGameType().getId(), getPlayBackDateTimeInfo());
            this.getRoomPlayBack().addPlayBack(playBackData);
        }
    }

    /**
     * 结算积分
     */
    public void calcPoint() {
        GameSetBO gameSetBO = ContainerMgr.get().getComponent(GameSetBOService.class).findOne(room.getRoomID(),
                this.room.getCurSetID());
        this.bo = gameSetBO == null ? new GameSetBO() : gameSetBO;
        if (gameSetBO == null) {
            bo.setRoomID(room.getRoomID());
            bo.setSetID(this.room.getCurSetID());
            bo.setTabId(this.room.getTabId());
        }

        this.resultCalc();

        for (int i = 0; i < this.room.getMaxPlayerNum(); i++) {
            ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(i);

            if (roomPos == null) {
                continue;
            }
            ZJHRoomSet set = (ZJHRoomSet) this.room.getCurSet();
            set.pointList.set(i, set.addScoreList.get(i));
        }

        if (RoomTypeEnum.UNION.equals(this.room.getRoomTypeEnum())) {
            this.onlyWinRightNowPoint();
            this.calYiKaoPoint();
        }

        for (int i = 0; i < this.room.getMaxPlayerNum(); i++) {
            ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(i);
            if (roomPos != null && roomPos.getPid() > 0) {
                ZJHRoom_PosEnd posEnd = roomPos.calcPosEnd();
                if (CollectionUtils.isNotEmpty(this.sportsPointList)) {
                    this.sportsPointList.set(posEnd.pos, Objects.isNull(posEnd.sportsPoint) ? 0D : posEnd.sportsPoint);
                }
                this.setEnd.posResultList.add(posEnd);
            }
        }
        CommLogD.info("posResultList -> " + new Gson().toJson(this.setEnd.posResultList));
        room.getRoomPosMgr().setAllLatelyOutCardTime();
        this.setEnd.endTime = CommTime.nowSecond();

        ZJHRoom_SetEnd lSetEnd = this.getNotify_setEnd();
        String gsonSetEnd = new Gson().toJson(lSetEnd);
        bo.setDataJsonRes(gsonSetEnd);
        bo.setEndTime(setEnd.endTime);
        bo.setPlayBackCode(getPlayBackDateTimeInfo().getPlayBackCode());
        bo.getBaseService().saveOrUpDate(bo);
    }

    /**
     * 获取通知设置
     *
     * @param pid 用户ID
     * @return
     */
    public ZJHRoomSetInfo getNotify_set(long pid) {
        ZJHRoomSetInfo ret = new ZJHRoomSetInfo();
        ret.setSetID(this.room.getCurSetID());
        ret.startTime = this.startMS;
        // 每个玩家的牌面
        ret.posInfo = new ArrayList<>();
        for (int i = 0; i < this.room.getPlayerNum(); i++) {
            ZJHRoomSet_Pos roomSet_Pos = this.getPosInfo(i, pid);

            ret.posInfo.add(roomSet_Pos);
        }
        ret.backerPos = this.getBackerPos();
        ret.state = this.state.value();

        ret.bottomPoint = this.m_bottomPoint;
        ret.opPos = this.m_opPos;
        ret.currTurns = this.m_currTurns;

        ret.upwardTimePos = this.upwardTimePos;
        ret.upwardOpTime = this.upwardOpTime;
        ret.upwardTime = this.room.upwardTimeValue();

        // if (this.status == ZJH_GameStatus.ZJH_GAME_STATUS_RESULT) {
        // ArrayList<ArrayList<Integer>> cards = new ArrayList<>();
        // for (int i = 0; i < this.room.getPlayerNum(); i++) {
        // ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(i);
        // cards.add(roomPos.getNotifyCard(roomPos.getPid()));
        // }
        // SZJH_SetEnd end = SZJH_SetEnd.make(this.room.getRoomID(),
        // this.status.value(), this.startMS, this.crawTypeList, this.pointList, cards,
        // this.sportsPointList);
        // ret.setEnd = end;
        // }
        return ret;
    }

    // 获取每个位置信息
    public ZJHRoomSet_Pos getPosInfo(int pos, long pid) {
        ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(pos);

        ZJHRoomSet_Pos posEnd = new ZJHRoomSet_Pos();

        posEnd.posID = roomPos.getPosID();
        posEnd.pid = roomPos.getPid();
        posEnd.cardList = roomPos.getNotifyCard(pid);
        posEnd.addBet = this.addScoreList.get(posEnd.posID);
        posEnd.isPlaying = this.playingList.get(posEnd.posID);
        posEnd.cardStatus = this.statusCardList.get(posEnd.posID);
        posEnd.recordList = this.m_RecordHMap.get(posEnd.posID);
        posEnd.isCallBacker = false;// this.getBackerPos() == posEnd.posID ? true : false;
        posEnd.crawType = this.cardTypeList.get(pos);
        posEnd.point = posEnd.addBet;
        return posEnd;
    }

    /**
     * 获取通知设置结束
     *
     * @return
     */
    public ZJHRoom_SetEnd getNotify_setEnd() {
        return setEnd;
    }

    /*
     * 判断牌的状态
     **/
    public boolean cheakCardStatus(int pos, int statusType) {
        int status = this.statusCardList.get(pos);
        return (status & statusType) > 0;
    }

    // 设置那些玩家在游戏中
    public void setPosPlaying(int pos, boolean flag) {
        playingList.set(pos, flag);
    }

    // 托管
    public void roomTrusteeship(int pos) {

        if (!this.playingList.get(pos))
            return;

        ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(pos);

        if (CommTime.nowMS() <= this.m_startMS + WAITTRUSTEESHIPTIME)
            return;

        if (this.cheakCardStatus(pos, ZJH_StatusType.GiveUp.value() | ZJH_StatusType.ComporeLose.value())) {
            return;
        }
        // YSJVB
        /*
         * if (! this.cheakCardStatus(pos, ZJH_StatusType.KaiPai.value()) ) {
         * if(Math.random()*100>this.room.getConfigMgr().getRobotOpenCard()){
         * this.setCardStatus(pos, ZJH_StatusType.KaiPai.value());
         * this.getRoomPlayBack().playBack2All(SZJH_OpCard.make(this.room.getRoomID(),
         * pos, ZJH_define.ZJH_OpType.KanPai.value(), 0, 0, false, m_opPos, m_startMS,
         * m_currTurns));
         * }
         * }
         */

        if (pos != m_opPos) {
            return;
        }
        if (this.m_currTurns > this.room.getLunShuShangXian()) {
            return;
        }

        if (this.getSurplusPlayerNum() < MINSURPLUSPLAYERNUM) {
            return;
        }

        if (!roomPos.isRobot()) {
            this.onPlayingTimeEnd();
            return;
        }

        if (this.cardTypeList.get(pos) == -1) {
            this.getCardTypeList();
        }

        int tempPos = this.randomPlayerPos();
        if (tempPos < 0) {
            this.onPlayingTimeEnd();
        } else if (this.cardTypeList.get(pos) < this.cardTypeList.get(tempPos)
                && Math.random() * 100 > this.room.getConfigMgr().getRobotQiPai()) {
            this.onPlayingTimeEnd();
        } else {
            int opType = ZJH_define.ZJH_OpType.GenZhu.value();
            int point = m_bottomPoint;
            int nextPoint = this.getNextJiaZhu();
            nextPoint = nextPoint > m_bottomPoint ? nextPoint : m_bottomPoint;
            boolean isKanPai = this.cheakCardStatus(pos, ZJH_StatusType.KaiPai.value());
            if (Math.random() * 100 > this.room.getConfigMgr().getRobotJiaZhu() && nextPoint > m_bottomPoint) {
                opType = ZJH_define.ZJH_OpType.JiaZhu.value();

                point = isKanPai ? nextPoint * 2 : nextPoint;

                m_bottomPoint = nextPoint;
            } else {
                point = isKanPai ? m_bottomPoint * 2 : m_bottomPoint;

            }
            this.addScoreList.set(pos, (int) (this.addScoreList.get(pos) - point));
            this.addOpPos();
            this.getRoomPlayBack().playBack2All(SZJH_OpCard.make(this.room.getRoomID(), pos, opType, point, 0, false,
                    m_opPos, m_startMS, m_currTurns));
        }

        switch (this.state) {
            case Settle:
            case End:
                if (!roomPos.isGameReady()) {
                    roomPos.setGameReady(true);
                    roomPos.setLatelyOutCardTime(0);
                }
                break;
            default:
                break;
        }
    }

    // 获取下一个等级的加注
    public int getNextJiaZhu() {
        ArrayList<Integer> jiaZhuList = this.room.getConfigMgr().getRobotJiaZhuList();
        for (Integer integer : jiaZhuList) {
            if (integer * this.room.getBaseMark() > m_bottomPoint) {
                return integer * this.room.getBaseMark();
            }
        }
        return m_bottomPoint;
    }

    // 随机一个玩家的位置出来
    public int randomPlayerPos() {
        int pos = (int) (Math.random() * this.room.getMaxPlayerNum());
        ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(pos);
        if (this.playingList.get(pos) && !roomPos.isRobot()
                && !this.cheakCardStatus(pos, ZJH_StatusType.GiveUp.value() | ZJH_StatusType.ComporeLose.value()))
            return pos;
        for (int i = 0; i < this.room.getMaxPlayerNum(); i++) {
            pos = (pos + 1) % this.room.getMaxPlayerNum();
            roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(pos);
            if (this.playingList.get(pos) && !roomPos.isRobot()
                    && !this.cheakCardStatus(pos, ZJH_StatusType.GiveUp.value() | ZJH_StatusType.ComporeLose.value()))
                return pos;
        }
        return -1;
    }

    /**
     * 操作
     */
    public void onOp(WebSocketRequest request, CZJH_OpCard data) {
        if (!this.playingList.get(data.pos)) {
            request.error(ErrorCode.NotAllow, "do not playing pos:" + data.pos);
            return;
        }

        if (this.cheakCardStatus(data.pos, ZJH_StatusType.GiveUp.value() | ZJH_StatusType.ComporeLose.value())) {
            request.error(ErrorCode.NotAllow, "give up crad or comporelose pos:" + data.pos);
            return;
        }

        // if(m_QuanYaPos != -1 && data.opType != ZJH_OpType.QuanYa.value()){
        // request.error(ErrorCode.NotAllow, "you must quan ya");
        // return;
        // }

        boolean result = false;
        switch (ZJH_define.ZJH_OpType.valueOf(data.opType)) {
            case QiPai:
                result = this.onQiPai(request, data);
                break;
            case GenZhu:
            case JiaZhu:
                result = this.onYaZhu(request, data);
                break;
            case QuanYa:
                result = this.onQuanYa(request, data);
                break;
            case BiPai:
                result = this.onBiPai(request, data);
                break;
            case KanPai:
                result = this.onKanPai(request, data);
                break;
            default:
                request.error(ErrorCode.NotAllow, "do not find optype:" + data.opType);
                break;
        }

        this.room.getRoomPosMgr().setAllLatelyOutCardTime();
        request.response();
        if (!result)
            return;

        if (this.state == SetState.End)
            return;

        if (ZJH_define.ZJH_OpType.KanPai.value() != data.opType) {
            if (!(m_QuanYaPos != -1 && m_QuanYaPos != data.pos))
                this.addOpPos();
        }

        if (m_QuanYaPos != -1 && m_QuanYaPos != data.pos) {
            this.getRoomPlayBack()
                    .playBack2All(SZJH_OpCard.make(data.roomID, data.pos, data.opType, data.addBet, m_QuanYaPos,
                            this.cheakCardStatus(data.pos, ZJH_StatusType.ComporeWin.value()), m_opPos, m_startMS,
                            m_currTurns));
        } else {
            this.getRoomPlayBack()
                    .playBack2All(SZJH_OpCard.make(data.roomID, data.pos, data.opType, data.addBet, data.comporePos,
                            this.cheakCardStatus(data.pos, ZJH_StatusType.ComporeWin.value()), m_opPos, m_startMS,
                            m_currTurns));
        }

        if (this.getSurplusPlayerNum() < MINSURPLUSPLAYERNUM) {
            this.endSet();
        }
        if (this.m_currTurns > this.room.getLunShuShangXian()) {
            this.endSet();
        }
        if (m_QuanYaPos != -1 && m_QuanYaPos != data.pos) {
            this.endSet();
        }
    }

    /*
     * 跟注
     */
    public boolean onYaZhu(WebSocketRequest request, CZJH_OpCard data) {
        if (data.pos != m_opPos) {
            request.error(ErrorCode.NotAllow, "Current position:" + m_opPos);
            return false;
        }

        if (m_QuanYaPos != -1) {
            request.error(ErrorCode.NotAllow, "you must quan ya");
            return false;
        }

        ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(data.pos);
        if (RoomTypeEnum.checkUnionOrClub(this.room.getRoomTypeEnum())) {
            if (roomPos.getRoomSportsPoint() < Math.abs((this.addScoreList.get(data.pos) - data.getAddBet()))) {
                request.error(ErrorCode.NotAllow, "竞技点不够，需要：{},你只有：{}", data.getAddBet(), roomPos.getRoomSportsPoint());
                if (this.upwardTimePos == -1) {
                    this.upwardTimePos = roomPos.getPosID();
                    this.upwardOpTime = CommTime.nowSecond();
                }
                this.room.getRoomPosMgr().notify2All(SZJH_UpwardPoint.make(this.room.getRoomID(), roomPos.getPosID(),
                        roomPos.getPid(), this.upwardOpTime, this.room.upwardTimeValue(), CommTime.nowSecond()));
                return false;
            }
        }

        boolean openCard = this.cheakCardStatus(data.pos, ZJH_StatusType.KaiPai.value());

        if (data.addBet > (openCard ? this.room.getDingZhu() * 2 : this.room.getDingZhu())) {
            request.error(ErrorCode.NotEnough_Currency, "add score than dingzhu :" + this.room.getDingZhu());
            return false;
        }

        int bottomPoint = (int) (openCard ? m_bottomPoint * 2 : m_bottomPoint);
        int num = this.cheakCardStatus(data.pos, ZJH_StatusType.KaiPai.value()) ? 2 : 1;
        boolean isBiPai = data.opType == ZJH_define.ZJH_OpType.BiPai.value();
        if (bottomPoint > data.addBet) {
            if (PrizeType.Gold == this.room.getValueType()
                    && roomPos.getPoint() + this.addScoreList.get(data.pos) < m_bottomPoint * num && data.addBet >= 0) {
                if (data.opType != ZJH_define.ZJH_OpType.BiPai.value()) {
                    request.error(ErrorCode.NotEnough_Currency,
                            "yazhu 1 fail  addScore:" + data.addBet + ",and bottomPoint:" + m_bottomPoint);
                    return false;
                }
            } else if (PrizeType.RoomCard == this.room.getValueType() && this.room.roomCfg.difen > 0
                    && roomPos.getPoint() + this.addScoreList.get(data.pos) < m_bottomPoint * num && data.addBet >= 0) {
                if (data.opType != ZJH_define.ZJH_OpType.BiPai.value()) {
                    request.error(ErrorCode.NotEnough_Currency,
                            "yazhu 2 fail  addScore:" + data.addBet + ",and bottomPoint:" + m_bottomPoint);
                    return false;
                }
            } else {

                // 关闭单倍比牌时， 不是比牌的话就抛出错误 panvc
                if (this.room.roomCfg.sbbp == 0) {
                    if (data.opType != ZJH_define.ZJH_OpType.BiPai.value()) {
                        request.error(ErrorCode.NotEnough_Currency,
                                "yazhu 3  fail  addScore:" + data.addBet + ",and bottomPoint:" + m_bottomPoint);
                        return false;
                    }
                } else {
                    request.error(ErrorCode.NotEnough_Currency,
                            "yazhu 4 fail  addScore:" + data.addBet + ",and bottomPoint:" + m_bottomPoint);
                    return false;
                }
            }

        }

        int point = openCard ? data.addBet / 2 : data.addBet;
        if (isBiPai && this.room.roomCfg.sbbp == 0) {
            point = point / 2;
        }
        if (point > m_bottomPoint) {
            m_bottomPoint = point;
        }

        this.addScoreList.set(data.pos, this.addScoreList.get(data.pos) - data.addBet);

        return true;
    }

    /*
     * 比牌
     */
    public boolean onBiPai(WebSocketRequest request, CZJH_OpCard data) {
        if (data.pos != m_opPos) {
            request.error(ErrorCode.NotAllow, "Current position:" + m_opPos);
            return false;
        }

        if (m_QuanYaPos != -1) {
            request.error(ErrorCode.NotAllow, "you must quan ya");
            return false;
        }

        if (data.pos == data.comporePos) {
            request.error(ErrorCode.NotAllow, "do not compare owner ");
            return false;
        }

        ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(data.pos);

        // int comporeCount = this.room.getConfigMgr().getComporeCountList().get(
        // this.room.roomCfg.kebilunshu);
        // 去掉可比轮数
        int comporeCount = 0;
        int num = this.cheakCardStatus(data.pos, ZJH_StatusType.KaiPai.value()) ? 2 : 1;
        if (m_currTurns < comporeCount) {
            if (PrizeType.Gold == this.room.getValueType()
                    && roomPos.getPoint() + this.addScoreList.get(data.pos) < m_bottomPoint * num) {
                if (data.opType != ZJH_define.ZJH_OpType.BiPai.value()) {
                    request.error(ErrorCode.NotAllow, "do not bipai kebilunshu:" + comporeCount);
                    return false;
                }
            } else if (PrizeType.RoomCard == this.room.getValueType() && this.room.roomCfg.difen > 0
                    && roomPos.getPoint() + this.addScoreList.get(data.pos) < m_bottomPoint * num) {
                if (data.opType != ZJH_define.ZJH_OpType.BiPai.value()) {
                    request.error(ErrorCode.NotAllow, "do not bipai kebilunshu:" + comporeCount);
                    return false;
                }
            } else {
                request.error(ErrorCode.NotAllow, "do not bipai kebilunshu:" + comporeCount);
                return false;
            }
        }

        if (this.room.getRoomCfg().sbbp == 0) {
            data.setAddBet(data.getAddBet() * 2);
        }
        if (!this.onYaZhu(request, data)) {
            return false;
        }

        ZJHRoomPos comporeRoomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(data.comporePos);

        if (ZJHGameLogic.CompareCard(roomPos.privateCards, comporeRoomPos.privateCards,
                this.room.roomCfg.tongpaishuying)) {
            this.setCardStatus(data.pos, ZJH_StatusType.ComporeWin.value());
            this.setCardStatus(data.comporePos, ZJH_StatusType.ComporeLose.value());

            this.m_RecordHMap.get(data.pos).add(new Victory(data.comporePos, ZJH_StatusType.ComporeWin.value()));
            this.m_RecordHMap.get(data.comporePos).add(new Victory(data.pos, ZJH_StatusType.ComporeLose.value()));

            comporeRoomPos.addLose(1);
        } else {
            this.setCardStatus(data.comporePos, ZJH_StatusType.ComporeWin.value());
            this.setCardStatus(data.pos, ZJH_StatusType.ComporeLose.value());

            this.m_RecordHMap.get(data.pos).add(new Victory(data.comporePos, ZJH_StatusType.ComporeLose.value()));
            this.m_RecordHMap.get(data.comporePos).add(new Victory(data.pos, ZJH_StatusType.ComporeWin.value()));

            roomPos.addLose(1);
        }

        return true;
    }

    /*
     * 看牌
     */
    public boolean onKanPai(WebSocketRequest request, CZJH_OpCard data) {

        if (this.m_currTurns < this.room.roomCfg.menpailunshu) {
            request.error(ErrorCode.NotAllow, "card do not open  pos is :" + data.pos + " " + this.m_currTurns + " "
                    + this.room.roomCfg.menpailunshu);
            return false;
        }
        if (this.cheakCardStatus(data.pos, ZJH_StatusType.KaiPai.value())) {
            request.error(ErrorCode.NotAllow, "card do not open  pos is :" + data.pos);
            return false;
        }

        this.setCardStatus(data.pos, ZJH_StatusType.KaiPai.value());

        return true;
    }

    /*
     * 全压
     */
    public boolean onQuanYa(WebSocketRequest request, CZJH_OpCard data) {
        if (data.pos != m_opPos) {
            request.error(ErrorCode.NotAllow, "Current position:" + m_opPos);
            return false;
        }

        if (this.getSurplusPlayerNum() != MINSURPLUSPLAYERNUM) {
            request.error(ErrorCode.NotEnough_Currency,
                    "player number not satisfy playernum:" + this.getSurplusPlayerNum());
            return false;
        }

        if (this.room.roomCfg.difen <= 0) {
            request.error(ErrorCode.NotAllow, "difen is 0, do not quanya");
            return false;
        }

        boolean openCard = this.cheakCardStatus(data.pos, ZJH_StatusType.KaiPai.value());
        ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(data.pos);

        int point = 0;
        if (PrizeType.Gold == this.room.getValueType()) {
            int otherPos = this.getOtherPlayer(data.pos);
            ZJHRoomPos otherRoomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(otherPos);

            boolean otherOpenCard = this.cheakCardStatus(otherPos, ZJH_StatusType.KaiPai.value());

            int myPoint = openCard ? roomPos.getPoint() / 2 : roomPos.getPoint();
            int otherPoint = otherOpenCard ? otherRoomPos.getPoint() / 2 : otherRoomPos.getPoint();

            point = myPoint > otherPoint ? otherPoint : myPoint;
            if (data.addBet > point) {
                request.error(ErrorCode.NotEnough_Currency, "quan ya score error quanyaScore:" + point);
                return false;
            }
        } else {
            if (data.addBet != this.room.getDingZhu() * this.room.getConfigMgr().getAddScoreAll()
                    * (openCard ? 2 : 1)) {
                request.error(ErrorCode.NotEnough_Currency, "quan ya score error quanyaScore:"
                        + (this.room.getDingZhu() * this.room.getConfigMgr().getAddScoreAll()));
                return false;
            }
        }

        if (m_QuanYaPos == -1) {
            m_QuanYaPos = data.pos;
            m_bottomPoint = openCard ? data.addBet / 2 : data.addBet;
            m_refund.setNum(data.addBet);
        } else {
            int bottomPoint = openCard ? data.addBet / 2 : data.addBet;
            if (bottomPoint < m_bottomPoint) {
                m_refund.setPos(m_QuanYaPos);
                boolean otherOpenCard = this.cheakCardStatus(m_QuanYaPos, ZJH_StatusType.KaiPai.value());
                int num = otherOpenCard ? bottomPoint * 2 : bottomPoint;
                m_refund.setNum(m_refund.getNum() - num);

                this.addScoreList.set(m_QuanYaPos, this.addScoreList.get(m_QuanYaPos) + m_refund.getNum() - num);
            }

            ZJHRoomPos comporeRoomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(m_QuanYaPos);

            if (ZJHGameLogic.CompareCard(roomPos.privateCards, comporeRoomPos.privateCards,
                    this.room.roomCfg.tongpaishuying)) {
                this.setCardStatus(data.pos, ZJH_StatusType.ComporeWin.value());
                this.setCardStatus(m_QuanYaPos, ZJH_StatusType.ComporeLose.value());

                this.m_RecordHMap.get(data.pos).add(new Victory(m_QuanYaPos, ZJH_StatusType.ComporeWin.value()));
                this.m_RecordHMap.get(m_QuanYaPos).add(new Victory(data.pos, ZJH_StatusType.ComporeLose.value()));

                comporeRoomPos.addLose(1);
            } else {
                this.setCardStatus(m_QuanYaPos, ZJH_StatusType.ComporeWin.value());
                this.setCardStatus(data.pos, ZJH_StatusType.ComporeLose.value());

                this.m_RecordHMap.get(data.pos).add(new Victory(m_QuanYaPos, ZJH_StatusType.ComporeLose.value()));
                this.m_RecordHMap.get(m_QuanYaPos).add(new Victory(data.pos, ZJH_StatusType.ComporeWin.value()));

                roomPos.addLose(1);
            }
        }

        this.addScoreList.set(data.pos, this.addScoreList.get(data.pos) - data.addBet);
        this.setCardStatus(data.pos, ZJH_StatusType.QuanYa.value());
        return true;
    }

    /*
     * 当只剩两个玩家的时候获取另外一个玩家
     */
    public int getOtherPlayer(int pos) {
        int otherPos = -1;
        if (this.getSurplusPlayerNum() != MINSURPLUSPLAYERNUM) {
            CommLogD.error("getOtherPlayer error: have more than two player");
            return otherPos;
        }
        for (int i = 0; i < this.room.getMaxPlayerNum(); i++) {
            if (!this.playingList.get(i))
                continue;
            if (this.cheakCardStatus(i, ZJH_StatusType.ComporeLose.value() | ZJH_StatusType.GiveUp.value()))
                continue;
            if (pos == i)
                continue;
            otherPos = i;
        }
        return otherPos;
    }

    /*
     * 弃牌
     */
    public boolean onQiPai(WebSocketRequest request, CZJH_OpCard data) {
        if (data.pos != m_opPos) {
            request.error(ErrorCode.NotAllow, "Current position:" + m_opPos);
            return false;
        }

        // YSJVB
        /*
         * if(!this.cheakCardStatus(data.pos, ZJH_StatusType.KaiPai.value())){
         * request.error(ErrorCode.NotAllow, "card do not open  pos is :" + data.pos);
         * return false;
         * }
         */
        this.giveUp(data.pos);

        return true;
    }

    // 翻牌
    public void onOpenCard(WebSocketRequest request, CZJH_OpenCard data) {
        if (!this.playingList.get(data.pos)) {
            request.error(ErrorCode.NotAllow, "do not playing pos:" + data.pos);
            return;
        }

        if (this.cheakCardStatus(data.pos, ZJH_StatusType.OpenCard.value())) {
            request.error(ErrorCode.NotAllow, "card open already pos:" + data.pos);
            return;
        }

        this.setCardStatus(data.pos, ZJH_StatusType.OpenCard.value());
        this.getRoomPlayBack().playBack2All(SZJH_OpenCard.make(data.roomID, data.pos));
    }

    // 翻牌
    public void onCheckCard(WebSocketRequest request, CZJH_CheckCard checkCard) {
        // if (this.getStatus() != ZJH_GameStatus.ZJH_GAME_STATUS_SENDCARD_SECOND) {
        // request.error(ErrorCode.NotAllow, "onAddScore is not
        // ZJH_GameStatus.ZJH_GAME_STATUS_SendCard error " + this.getStatus());
        // return;
        // }
        //
        // if (this.checkCardList.get(checkCard.pos)) {
        // request.error(ErrorCode.NotAllow, "onAddScore is alary checkCard error " +
        // checkCard.pos);
        // return;
        // }
        // request.response();
        // this.checkCardList.set(checkCard.pos, true);
    }

    // 当前几个人在玩
    public int getPlayingCount() {
        int count = 0;
        for (boolean flag : this.playingList) {
            if (flag)
                count++;
        }
        return count;
    }

    // 是否所有玩家都下注
    public boolean cheakAllBet() {
        for (int i = 0; i < this.room.getMaxPlayerNum(); i++) {
            if (i == this.getBackerPos())
                continue;
            if (this.playingList.get(i) && this.betList.get(i) <= 0) {
                return false;
            }
        }
        return true;
    }

    // 是否所有玩家都开牌
    public boolean cheakAllOpenCard() {
        for (int i = 0; i < this.room.getMaxPlayerNum(); i++) {
            if (this.playingList.get(i) && !this.openCardList.get(i)) {
                return false;
            }
        }
        return true;
    }

    /*
     * 设置是否抢庄
     */
    public void setCallBacker(int pos, int callBackerNum) {
        boolean flag = false;
        try {
            if (this.callbackerList.size() > 0) {
                for (Victory vic : this.callbackerList) {
                    if (null == vic)
                        continue;
                    if (pos == vic.getPos()) {
                        vic.setNum(callBackerNum);
                        flag = true;
                    }
                }
            }
            if (!flag) {
                if (this.callbackerList == null)
                    this.callbackerList = new ArrayList<Victory>();
                Victory vic = new Victory(pos, callBackerNum);
                this.callbackerList.add(vic);
            }
        } catch (Exception e) {
            CommLogD.error("getCallbackerNum error:", e);
        }
        return;
    }

    /*
     * 抢庄倍数
     */
    @SuppressWarnings("finally")
    public int getCallbackerNum(int pos) {
        int flag = -1;
        try {
            if (this.callbackerList.size() <= 0)
                return flag;
            for (Victory vic : this.callbackerList) {
                if (null == vic)
                    continue;
                if (vic.getPos() == pos) {
                    flag = vic.getNum();
                    break;
                }
            }
            // CommLogD.info("getCallbackerNum num:%s ,pos:%s", flag, pos);
            // if(this.callbackerList.size() > 0) {
            // CommLogD.info("this.callbackerList.toString():%s",
            // this.callbackerList.toString());
            // }
        } catch (Exception e) {
            CommLogD.error("getCallbackerNum error:", e);
        } finally {
            return flag;
        }
    }

    // 有没有抢庄的
    @SuppressWarnings("finally")
    public int getCallBackerCount() {
        int count = 0;
        try {
            if (this.callbackerList.size() <= 0)
                return count;
            for (Victory vic : this.callbackerList) {
                if (null == vic)
                    continue;
                if (vic.getNum() >= 1) {
                    count++;
                }
            }
        } catch (Exception e) {
            CommLogD.error("getCallBackerCount error:", e);
        } finally {
            return count;
        }
    }

    /**
     * @return backerPos
     */
    public int getBackerPos() {
        return this.m_backerPos;
    }

    /**
     * @param backerPos 要设置的 backerPos
     */
    public void setBackerPos(int backerPos, boolean isRandBackerPos) {
        this.m_backerPos = backerPos;
        this.m_isRandBackPos = isRandBackerPos;

        if (this.getCallbackerNum(backerPos) <= 0)
            this.setCallBacker(backerPos, 1);
    }

    /*
     * 牌验证
     **/
    public boolean checkCardList(int pos, ArrayList<Integer> cardList) {
        ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(pos);
        for (Integer byte1 : cardList) {
            if (!roomPos.privateCards.contains(byte1)) {
                return false;
            }
        }
        return true;
    }

    // 在玩家中随机一个玩家位置出来
    public int getRandPos() {
        int randPos = (int) (Math.random() * this.room.getPlayingCount());
        if (!this.playingList.get(randPos)) {
            for (int i = 0; i < this.room.getMaxPlayerNum(); i++) {
                randPos = (randPos + 1) % this.room.getMaxPlayerNum();
                if (this.playingList.get(randPos)) {
                    break;
                }
            }
        }
        return randPos;
    }

    // 获取历史set
    public ZJHRoomSet getHisSet(int setID) {
        if (room.getHistorySetSize() > setID)
            return (ZJHRoomSet) room.getHistorySet(setID);
        return null;
    }

    /**
     * 设置神牌
     */
    private void godCard() {
        if (!room.isGodCard()) {
            return;
        }
        boolean flag1 = BasePockerLogic.deleteCard(this.setCard.getLeftCards(), room.getConfigMgr().getPrivate_Card1());
        boolean flag2 = BasePockerLogic.deleteCard(this.setCard.getLeftCards(), room.getConfigMgr().getPrivate_Card2());
        boolean flag3 = BasePockerLogic.deleteCard(this.setCard.getLeftCards(), room.getConfigMgr().getPrivate_Card3());
        boolean flag4 = BasePockerLogic.deleteCard(this.setCard.getLeftCards(), room.getConfigMgr().getPrivate_Card4());
        boolean flag5 = BasePockerLogic.deleteCard(this.setCard.getLeftCards(), room.getConfigMgr().getPrivate_Card5());
        boolean flag6 = BasePockerLogic.deleteCard(this.setCard.getLeftCards(), room.getConfigMgr().getPrivate_Card6());
        boolean flag7 = BasePockerLogic.deleteCard(this.setCard.getLeftCards(), room.getConfigMgr().getPrivate_Card7());
        boolean flag8 = BasePockerLogic.deleteCard(this.setCard.getLeftCards(), room.getConfigMgr().getPrivate_Card8());
        if (flag1 && flag2 && flag3 && flag4 && flag5 && flag6 && flag7 && flag8) {
            ArrayList<Integer> card1 = getGodCard(room.getConfigMgr().getPrivate_Card1());
            ArrayList<Integer> card2 = getGodCard(room.getConfigMgr().getPrivate_Card2());
            ArrayList<Integer> card3 = getGodCard(room.getConfigMgr().getPrivate_Card3());
            ArrayList<Integer> card4 = getGodCard(room.getConfigMgr().getPrivate_Card4());
            ArrayList<Integer> card5 = getGodCard(room.getConfigMgr().getPrivate_Card5());
            ArrayList<Integer> card6 = getGodCard(room.getConfigMgr().getPrivate_Card6());
            ArrayList<Integer> card7 = getGodCard(room.getConfigMgr().getPrivate_Card7());
            ArrayList<Integer> card8 = getGodCard(room.getConfigMgr().getPrivate_Card8());
            hMap.put(0, card1);
            hMap.put(1, card2);
            hMap.put(2, card3);
            hMap.put(3, card4);
            hMap.put(4, card5);
            hMap.put(5, card6);
            hMap.put(6, card7);
            hMap.put(7, card8);
        } else {
            int cardNum = this.room.maxCardCount;
            hMap.put(0, this.setCard.popList(cardNum));
            hMap.put(1, this.setCard.popList(cardNum));
            hMap.put(2, this.setCard.popList(cardNum));
            hMap.put(3, this.setCard.popList(cardNum));
            hMap.put(4, this.setCard.popList(cardNum));
            hMap.put(5, this.setCard.popList(cardNum));
            hMap.put(6, this.setCard.popList(cardNum));
            hMap.put(7, this.setCard.popList(cardNum));
        }
    }

    /**
     * 插入牌 并在牌堆里面删除
     */
    public ArrayList<Integer> getGodCard(ArrayList<Integer> list) {
        if (!room.isGodCard()) {
            return new ArrayList<>();
        }
        int cardNum = this.room.maxCardCount;
        ArrayList<Integer> cardList = new ArrayList<Integer>(cardNum);
        cardList.addAll(list);
        int count = cardNum - cardList.size();
        ArrayList<Integer> tempList = this.setCard.popList(count);
        BasePockerLogic.deleteCard(this.setCard.getLeftCards(), tempList);
        cardList.addAll(tempList);
        return cardList;
    }

    /**
     * @return m_isRandBackPos
     */
    public boolean isRandBackPos() {
        return m_isRandBackPos;
    }

    @Override
    public void clear() {
        this.room = null;
        if (null != this.setCard) {
            this.setCard = null;
        }
        // this.pointList = null;
        this.openCardList = null;
        this.setEnd = null;
        this.hMap = null;
    }

    @Override
    public void addDissolveRoom(BaseSendMsg baseSendMsg) {
        ZJHRoomPosMgr roomPosMgr = (ZJHRoomPosMgr) this.room.getRoomPosMgr();
        this.getRoomPlayBack().addPlaybackList(baseSendMsg, roomPosMgr.getAllPlayBackNotify());
    }

    @Override
    public boolean checkExistPrizeType(PrizeType prizeType) {
        return prizeType.equals(this.room.getBaseRoomConfigure().getPrizeType());
    }

    @Override
    public void clearBo() {
        this.bo = null;
    }

    /**
     * 标识Id
     *
     * @return
     */
    @Override
    public int getTabId() {
        return this.room.getTabId();
    }

    /**
     * 每200ms更新1次 秒
     * 
     * @param sec
     * @return T 是 F 否
     */
    public boolean update(int sec) {
        boolean isClose = false;

        if (this.state == SetState.Init) {
        } else if (this.state == SetState.Playing) {

            if (CommTime.nowMS() > this.m_startMS + ONEPLAYERPLAYINGTIME) {
                this.onPlayingTimeEnd();
            }

            if (this.m_currTurns > this.room.getLunShuShangXian()) {
                this.endSet();
            }

            if (this.getSurplusPlayerNum() < MINSURPLUSPLAYERNUM) {
                this.endSet();
            }
        } else if (this.state == SetState.End) {
            isClose = true;
        }
        return isClose;
    }

    // 获取剩余玩家个数
    public int getSurplusPlayerNum() {
        int count = 0;
        for (int i = 0; i < this.room.getMaxPlayerNum(); i++) {
            if (!this.playingList.get(i))
                continue;
            if (this.cheakCardStatus(i,
                    ZJH_define.ZJH_StatusType.ComporeLose.value() | ZJH_define.ZJH_StatusType.GiveUp.value()))
                continue;
            count++;
        }
        return count;
    }

    /*
     * 时间到了操作
     */
    public void onPlayingTimeEnd() {
        if (this.m_currTurns > this.room.getLunShuShangXian()) {
            return;
        }

        if (this.getSurplusPlayerNum() < MINSURPLUSPLAYERNUM) {
            return;
        }

        int tempPos = m_opPos;
        this.giveUp(tempPos);
        this.addOpPos();
        this.getRoomPlayBack().playBack2All(SZJH_OpCard.make(this.room.getRoomID(), tempPos,
                ZJH_define.ZJH_OpType.QiPai.value(), 0, 0, false, m_opPos, m_startMS, m_currTurns));

        if (this.upwardTimePos != -1) {
            this.upwardTimePos = -1;
        }
        // zhaozw 托管弃牌之后检查是否解散
        if (this.getSurplusPlayerNum() < MINSURPLUSPLAYERNUM) {
            this.endSet();
        }
    }

    // 这是该谁出牌
    public void addOpPos() {
        for (int i = 0; i < this.room.getMaxPlayerNum(); i++) {
            m_opPos = (m_opPos + 1) % this.room.getMaxPlayerNum();
            if (this.playingList.get(m_opPos) && !this.cheakCardStatus(m_opPos,
                    ZJH_StatusType.ComporeLose.value() | ZJH_StatusType.GiveUp.value()))
                break;
        }

        this.m_startMS = CommTime.nowMS();

        int tempPos = m_currTurnOpPos;
        // while (this.cheakCardStatus(m_currTurnOpPos,
        // ZJH_StatusType.ComporeLose.value() | ZJH_StatusType.GiveUp.value())) {
        // m_currTurnOpPos = (m_currTurnOpPos+1)%this.room.getMaxPlayerNum();
        // while (!this.playingList.get(m_currTurnOpPos)) {
        // m_currTurnOpPos = (m_currTurnOpPos+1)%this.room.getMaxPlayerNum();
        // }
        // }

        if (this.cheakCardStatus(m_currTurnOpPos, ZJH_StatusType.ComporeLose.value() | ZJH_StatusType.GiveUp.value())) {
            for (int i = 0; i < this.room.getMaxPlayerNum(); i++) {
                m_currTurnOpPos = (m_currTurnOpPos + 1) % this.room.getMaxPlayerNum();
                if (this.playingList.get(m_currTurnOpPos) && !this.cheakCardStatus(m_currTurnOpPos,
                        ZJH_StatusType.ComporeLose.value() | ZJH_StatusType.GiveUp.value()))
                    break;
            }
        }

        if (tempPos != m_currTurnOpPos)
            return;

        if (m_currTurnOpPos == m_opPos) {
            m_currTurns++;
            m_currTurnOpPos = m_opPos;
        }
    }

    /*
     * 弃牌
     */
    public void giveUp(int pos) {
        this.setCardStatus(pos, ZJH_StatusType.GiveUp.value());

        ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(pos);
        roomPos.addLose(1);
    }

    @Override
    public void recordRoomPosPointBeginStart() {
        if (this.room.isOnlyWinRightNowPoint() && RoomTypeEnum.UNION.equals(this.room.getRoomTypeEnum())) {
            for (int i = 0; i < room.getPlayerNum(); i++) {
                AbsRoomPos roomPos = this.room.getRoomPosMgr().getPosByPosID(i);
                if (roomPos == null || roomPos.getPid() == 0) {
                    continue;
                }
                roomPos.setGameBeginSportsPoint(roomPos.getRoomSportsPoint());
            }
        }
    }

    /**
     * 亲友圈竞技点不能输到0分
     */
    @SuppressWarnings("Duplicates")
    public void onlyWinRightNowPoint() {
        // 各个位置的算分情况map
        double beiShu = Math.max(0D, this.room.getRoomTyepImpl().getSportsDouble());
        // 临时存储玩家最多输赢分
        Map<Integer, Double> deductPointTemp = new HashMap<>();
        // 最后玩家应该输赢的竞技点
        Map<Integer, Double> resultPointTemp = new HashMap<>();
        // 各个位置的输分情况
        Map<Integer, Double> pointMap = new HashMap<>();
        // 各个位置的最多能赢多少分
        Map<Integer, Double> sportPointMap = new HashMap<>();
        // 不同的情况 初始化的数据来源不同
        Integer huMax = this.pointList.stream().max(Comparator.comparingInt(Integer::intValue)).get();
        int huPos = pointList.indexOf(huMax);
        if (room.isOnlyWinRightNowPoint() && RoomTypeEnum.UNION.equals(room.getRoomTypeEnum())) {
            // 身上多少分赢多少分
            // 初始化一科计算分数所需要的map
            for (int i = 0; i < yiKaoPointList.size(); i++) {
                yiKaoPointList.set(i, CommMath.mul(pointList.get(i), beiShu));
            }
        }
        // 不同的情况 初始化的数据来源不同
        if (room.isRulesOfCanNotBelowZero() && RoomTypeEnum.UNION.equals(room.getRoomTypeEnum()) && huPos >= 0) {
            for (int i = 0; i < this.room.getMaxPlayerNum(); i++) {
                ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(i);
                if (roomPos == null) {
                    pointMap.put(i, 0D);
                    sportPointMap.put(i, 0D);
                    // 更新临时存储值
                    deductPointTemp.put(i, 0D);
                    resultPointTemp.put(i, 0D);
                } else {
                    pointMap.put(i, yiKaoPointList.get(i));
                    sportPointMap.put(i, roomPos.getGameBeginSportsPoint());
                    // 更新临时存储值
                    deductPointTemp.put(i, yiKaoPointList.get(i));
                    if (yiKaoPointList.get(i) > 0) {
                        resultPointTemp.put(i, yiKaoPointList.get(i));
                    } else {
                        resultPointTemp.put(i, 0D);
                    }
                }
            }
        } else if (room.isOnlyWinRightNowPoint() && RoomTypeEnum.UNION.equals(room.getRoomTypeEnum()) && huPos >= 0) {
            // 初始化一科计算分数所需要的map
            for (int i = 0; i < this.room.getMaxPlayerNum(); i++) {
                ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(i);
                if (roomPos == null) {
                    pointMap.put(i, 0D);
                    sportPointMap.put(i, 0D);
                    // 更新临时存储值
                    deductPointTemp.put(i, 0D);
                    resultPointTemp.put(i, 0D);
                } else {
                    pointMap.put(i, CommMath.mul(pointList.get(i), beiShu));
                    sportPointMap.put(i, roomPos.getGameBeginSportsPoint());
                    // 更新临时存储值
                    deductPointTemp.put(i, yiKaoPointList.get(i));
                    if (yiKaoPointList.get(i) > 0) {
                        resultPointTemp.put(i, yiKaoPointList.get(i));
                    } else {
                        resultPointTemp.put(i, 0D);
                    }
                }
            }
        }

        // 如果全部都在正常范围，按正常算分
        boolean flag = false;
        for (int i = 0; i < this.room.getMaxPlayerNum(); i++) {
            ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(i);
            if (roomPos == null) {
                continue;
            }
            boolean allMatch = roomPos.getGameBeginSportsPoint() < 0
                    || CommMath.subDouble(yiKaoPointList.get(i), roomPos.getGameBeginSportsPoint()) <= 0D;
            if (!allMatch) {
                flag = true;
                break;
            }
        }

        if (!flag) {
            return;
        }

        boolean isFirst = false;
        // 只能赢自己身上的分数
        if (room.isOnlyWinRightNowPoint() && RoomTypeEnum.UNION.equals(this.room.getRoomTypeEnum()) && huPos >= 0) {
            for (int i = 0; i < this.room.getMaxPlayerNum(); i++) {
                ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(i);
                if (roomPos == null) {
                    continue;
                }
                Double losePoint = yiKaoPointList.get(i);
                // 没有赢分的话 不进行考虑
                if (losePoint <= 0) {
                    continue;
                }
                // 需要扣减的分数
                Double needSubPoint = CommMath.subDouble(losePoint, roomPos.getGameBeginSportsPoint());
                // 有需要扣减的话进行扣减
                if (needSubPoint > 0D) {
                    Map<Integer, Double> resultMap = this.subPointByOnlyWinRightNowPoint(deductPointTemp, i, isFirst,
                            !isFirst ? this.getExceptOneOtherPoint() : 0);
                    for (int j = 0; j < this.room.getMaxPlayerNum(); j++) {
                        ZJHRoomPos roomPosJ = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(j);
                        if (roomPosJ == null) {
                            continue;
                        }
                        if (resultMap.get(j) < 0) {
                            // 分数进行增减
                            deductPointTemp.put(j,
                                    CommMath.addDouble(deductPointTemp.get(j), Math.abs(resultMap.get(j))));
                            resultPointTemp.put(j, CommMath.addDouble(resultPointTemp.get(j), resultMap.get(j)));
                        } else {
                            if (j == i) {
                                resultPointTemp.put(j, resultMap.get(j));
                            }
                        }
                    }
                    isFirst = true;
                }
            }
            for (int j = 0; j < this.room.getMaxPlayerNum(); j++) {
                ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(j);
                if (roomPos == null) {
                    continue;
                }
                yiKaoPointList.set(j, resultPointTemp.get(j));
            }
        }
    }

    /**
     * @param posId   多赢的那个人
     * @param isFirst
     **/
    private Map<Integer, Double> subPointByOnlyWinRightNowPoint(Map<Integer, Double> temp, int posId, boolean isFirst,
            Double otherPoint) {
        Map<Integer, Double> resultMap = new HashMap<>(temp);
        // 传递参数使用
        Map<Integer, Double> resultMap2 = new HashMap<>(resultMap);

        Long newPlayerNum = resultMap.entrySet().stream().filter(k -> k.getValue() < 0).count();
        ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(posId);
        Double beginGamePoint = CommMath.addDouble(roomPos.getGameBeginSportsPoint(), otherPoint);
        Double newMin = CommMath.div(-beginGamePoint, newPlayerNum.intValue());
        Double minValue = resultMap.entrySet().stream().filter(k -> k.getValue() < 0)
                .sorted(Comparator.comparing(k -> -k.getValue())).map(k -> k.getValue()).findFirst().orElse(0D);
        Map<Integer, Double> calcMap = this.diGuiMethod(beginGamePoint, resultMap2, minValue, newMin);

        Double addDouble = 0D;
        for (Map.Entry<Integer, Double> con : calcMap.entrySet()) {
            if (con.getValue() > 0) {
                if (con.getKey().intValue() == posId) {
                    resultMap.put(con.getKey(), CommMath.subDouble(beginGamePoint, otherPoint));
                }
            }
            if (con.getValue() == 0) {
                addDouble = CommMath.addDouble(addDouble, Math.abs(resultMap.get(con.getKey())));
            }
        }
        long count = calcMap.entrySet().stream().filter(k -> k.getValue() < 0).count();
        // 计算除后余不进的值，加输分最高的第一个人（例：剩10，平均3份。每人3.33，还差0.1补给第一分最低的人）
        // 剩余的份数10
        double levelNum = CommMath.subDouble(beginGamePoint, addDouble);
        // 平均每人3.33
        double everyCount = CommMath.div(levelNum, count);
        // 还差0.01
        double difference = CommMath.subDouble(levelNum, CommMath.mul(everyCount, count));
        for (Map.Entry<Integer, Double> con : calcMap.entrySet()) {
            if (con.getValue() < 0) {
                double point = -everyCount;
                if (difference != 0) {
                    point = CommMath.addDouble(point, -difference);
                    difference = 0;
                }
                resultMap.put(con.getKey(), point);
            }
        }
        return resultMap;
    }

    /**
     * 递归方法
     *
     * @param beginGamePoint
     * @param resultMap
     * @param minValue
     * @return
     **/
    private Map<Integer, Double> diGuiMethod(double beginGamePoint, Map<Integer, Double> resultMap, double minValue,
            double avgrPoint) {
        Long belowZero = resultMap.entrySet().stream().filter(k -> k.getValue() < 0).count();
        boolean allBeolo = resultMap.entrySet().stream()
                .allMatch(k -> k.getValue() >= 0 || (k.getValue() <= avgrPoint));

        if (belowZero.intValue() == 1 || allBeolo) {
            return resultMap;
        }

        for (Map.Entry<Integer, Double> con : resultMap.entrySet()) {
            if (con.getValue() >= 0) {
                continue;
            }
            resultMap.put(con.getKey(), CommMath.addDouble(con.getValue(), Math.abs(minValue)));
            beginGamePoint = CommMath.subDouble(beginGamePoint, Math.abs(minValue));
        }
        Long newPlayerNum = resultMap.entrySet().stream().filter(k -> k.getValue() < 0).count();
        Double newMin = CommMath.div(-beginGamePoint, newPlayerNum.intValue());
        minValue = resultMap.entrySet().stream().filter(k -> k.getValue() > newMin && k.getValue() < 0)
                .sorted(Comparator.comparing(k -> -k.getValue())).map(k -> k.getValue()).findFirst().orElse(0D);
        return diGuiMethod(beginGamePoint, resultMap, minValue, newMin);
    }

    /**
     * 获取除了某个玩家外 其他玩家 分数超过带多少赢的
     *
     * @return
     **/
    private Double getExceptOneOtherPoint() {
        Double totalValue = new Double(0D);
        for (int i = 0; i < room.getMaxPlayerNum(); i++) {
            ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(i);
            if (roomPos == null) {
                continue;
            }
            if (yiKaoPointList.get(i) <= 0 || yiKaoPointList.get(i) > roomPos.getGameBeginSportsPoint()) {
                continue;
            }
            totalValue = CommMath.addDouble(totalValue, yiKaoPointList.get(i));
        }
        return totalValue;
    }

    /**
     * 亲友圈竞技点不能输到0分
     **/
    @SuppressWarnings("Duplicates")
    public void calYiKaoPoint() {
        // 各个位置的算分情况map
        double beiShu = Math.max(0D, this.room.getRoomTyepImpl().getSportsDouble());

        // 各个位置的输分情况
        Map<Integer, Double> pointMap = new HashMap<>();
        // 各个位置的最多能输多少分
        Map<Integer, Double> sportPointMap = new HashMap<>();
        if (!(room.isOnlyWinRightNowPoint() && RoomTypeEnum.UNION.equals(room.getRoomTypeEnum()))) {
            // 身上多少分赢多少分
            // 初始化一科计算分数所需要的map
            for (int i = 0; i < this.room.getMaxPlayerNum(); i++) {
                ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(i);

                if (roomPos == null) {
                    continue;
                }
                yiKaoPointList.set(i, CommMath.mul(pointList.get(i), beiShu));
            }
        }
        // 初始化一科计算分数所需要的map
        for (int i = 0; i < this.room.getMaxPlayerNum(); i++) {
            ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(i);
            if (roomPos == null) {
                pointMap.put(i, 0D);
                sportPointMap.put(i, 0D);
            } else {
                pointMap.put(i, CommMath.mul(pointList.get(i), beiShu));
                sportPointMap.put(i, roomPos.getRoomSportsPoint());
            }
        }
        // 不同的情况 初始化的数据来源不同
        Integer huMax = this.pointList.stream().max(Comparator.comparingInt(Integer::intValue)).get();
        int huPos = pointList.indexOf(huMax);
        // 亲友圈竞技点不能输到0分
        if (room.isRulesOfCanNotBelowZero() && RoomTypeEnum.UNION.equals(this.room.getRoomTypeEnum()) && huPos >= 0) {
            Double totalWinPoint = 0D;// 输的总分
            for (int i = 0; i < this.room.getMaxPlayerNum(); i++) {
                ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(i);
                if (roomPos == null) {
                    continue;
                }
                Double losePoint = yiKaoPointList.get(i);// -12
                if (losePoint <= 0) {
                    // 如果这个玩家本身没有分数可以扣 设置为0 继续下一个玩家计算
                    if (sportPointMap.get(i) <= 0) {
                        yiKaoPointList.set(i, 0D);
                        continue;
                    }
                    // 一科分数限制 10
                    if (sportPointMap.get(i) - Math.abs(losePoint) < 0) {
                        // 输的分数为-的
                        losePoint = CommMath.mul(sportPointMap.get(i), -1);
                        yiKaoPointList.set(i, losePoint);
                    }
                    totalWinPoint = CommMath.addDouble(totalWinPoint, Math.abs(losePoint));
                }
            }
            for (int i = 0; i < this.room.getMaxPlayerNum(); i++) {
                ZJHRoomPos roomPos = (ZJHRoomPos) this.room.getRoomPosMgr().getPosByPosID(i);
                if (roomPos == null) {
                    continue;
                }
                Double winPoint = yiKaoPointList.get(i);// 12
                if (totalWinPoint <= 0) {
                    for (int j = i; j < this.room.getMaxPlayerNum(); j++) {
                        if (yiKaoPointList.get(j) >= 0) {
                            yiKaoPointList.set(j, 0D);
                        }
                    }
                    break;
                }
                if (winPoint > 0) {
                    if (totalWinPoint < winPoint) {
                        yiKaoPointList.set(i, totalWinPoint);
                        totalWinPoint = CommMath.subDouble(totalWinPoint, totalWinPoint);
                    } else {
                        totalWinPoint = CommMath.subDouble(totalWinPoint, winPoint);
                    }
                }
            }

        }
    }

    public void kickOut(List<Long> pids) {
        this.room.getRoomPosMgr().getPosList().forEach(x -> {
            if (pids.contains(x.getPid())) {
                ZJHRoomPos xx = (ZJHRoomPos) x;
                xx.clearKickOut();
            }
        });
    }
}
